package com.heima.wemedia.service.impl;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.common.constants.WemediaConstants;
import com.heima.common.exception.CustomException;
import com.heima.model.common.dtos.PageResponseResult;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.wemedia.dtos.WmNewsDto;
import com.heima.model.wemedia.dtos.WmNewsPageReqDto;
import com.heima.model.wemedia.pojos.WmMaterial;
import com.heima.model.wemedia.pojos.WmNews;
import com.heima.model.wemedia.pojos.WmNewsMaterial;
import com.heima.utils.common.WmThreadLocalUtil;
import com.heima.wemedia.mapper.WmMaterialMapper;
import com.heima.wemedia.mapper.WmNewsMapper;
import com.heima.wemedia.mapper.WmNewsMaterialMapper;
import com.heima.wemedia.service.WmNewsAutoScanService;
import com.heima.wemedia.service.WmNewsService;
import com.heima.wemedia.service.WmNewsTaskService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class WmNewsServiceImpl extends ServiceImpl<WmNewsMapper, WmNews> implements WmNewsService {
    @Autowired
    private WmNewsAutoScanService wmNewsAutoScanService;
    @Autowired
    private WmNewsTaskService wmNewsTaskService;
    /**
     * 查询所有文章
     * @param dto
     * @return
     */
    @Override
    public ResponseResult selectAll(WmNewsPageReqDto dto) {
        //校验穿过来的参数
        if (null==dto){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        dto.checkParam();//校验分页参数
        //构建分页
        Page<WmNews> page = new Page<>(dto.getPage(),dto.getSize());
        LambdaQueryWrapper<WmNews> queryWrapper = new LambdaQueryWrapper<>();
        //1.查询状态
        if (dto.getStatus()!=null){
            queryWrapper.eq(WmNews::getStatus,dto.getStatus());
        }
        //2.查询频道
        if (null!=dto.getChannelId()){
            queryWrapper.eq(WmNews::getChannelId,dto.getChannelId());
        }
        //3.查询关键字
        if (null!=dto.getKeyword()){
            queryWrapper.like(WmNews::getTitle,dto.getKeyword());
        }
        //4.查询时间
        if (null!=dto.getEndPubDate()&&null!=dto.getBeginPubDate()){
            queryWrapper.between(WmNews::getSubmitedTime,dto.getBeginPubDate(),dto.getEndPubDate());
        }
        queryWrapper.orderByDesc(WmNews::getSubmitedTime);
        page = this.page(page, queryWrapper);//构建分页条件
        ResponseResult responseResult = new PageResponseResult(dto.getPage(),dto.getSize(),(int)page.getTotal());
        responseResult.setData(page.getRecords());
        return responseResult;
//        //1.校验dto中的参数是否为空
//        if (null==dto||dto.getSize()==0){
//            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
//        }
//        Page<WmNews> wmNewsPage = new Page<>(dto.getPage(),dto.getSize());//创建分页对象
//        LambdaQueryWrapper<WmNews> wrapper = new LambdaQueryWrapper<>();
//        //判断分页的条件
//        dto.checkParam();//创建之前鉴别一下参数,如果没传page就给一个默认值.
//        //判断条件
//        if (dto.getStatus()!=null){
//             wrapper.eq(WmNews::getStatus,dto.getStatus());
//        }
//        if (StringUtils.isNotBlank(dto.getKeyword())){
//            wrapper.like(WmNews::getTitle,dto.getKeyword());
//        }
//        if (null!=dto.getChannelId()){
//            wrapper.eq(WmNews::getChannelId,dto.getChannelId());
//        }
//        //时间范围查找
//        if (dto.getBeginPubDate()!=null&&null!=dto.getEndPubDate()){
//            wrapper.between(WmNews::getCreatedTime,dto.getBeginPubDate(),dto.getEndPubDate());
//        }
//        wrapper.orderByDesc(WmNews::getCreatedTime);//按照时间倒序的顺序来排序,让最先发布的先看到
//        Page<WmNews> page = this.page(wmNewsPage, wrapper);
//        ResponseResult result = new PageResponseResult(dto.getPage(),dto.getSize(), (int) page.getTotal());
//        result.setData(page.getRecords());
//        return result;
    }

    /**
     * 发布文章
     * @param dto
     * @return
     */
    @Override
    public ResponseResult submit(WmNewsDto dto) throws Exception {
        //1.校验dto中的参数:内容是否为空,内容为空直接返回.以及dto是否为空
        if (null==dto||StringUtils.isBlank(dto.getContent())){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        //2.保存或者修改文章表
        WmNews wmNews=saveorupdateNews(dto);
        //3.判断状态是否是草稿,如果是就直接返回成功
        if (dto.getStatus()==WmNews.Status.NORMAL.getCode()){
            return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
        }
        //4.将内容中的图片抽取出来,出来的是集合
        List<String> materials = ectractUrlInfo(dto.getContent());
        //5.保存内容中的图片到联系表
        saveContentImg(materials,wmNews);
        //6.保存封面中的图片到联系表
        saveCoverImg(materials,wmNews,dto);
        //异步调用审核文章
        //wmNewsAutoScanService.autoScanWmNews(wmNews.getId());
        wmNewsTaskService.addWmNewsToTask(wmNews);//调用将任务添加到redis中
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }
    /**
     * 6.保存封面中的图片到关联表中
     * @param materials
     * @param wmNews
     * @param dto
     */
    private void saveCoverImg(List<String> materials, WmNews wmNews, WmNewsDto dto) {
        //1.先判断dto里面发布文章是不是选择的是不是自动
        if (dto.getType()==WemediaConstants.WM_NEWS_TYPE_AUTO){
            if (null==materials){//内容没有图,选择的是自动,那么自动也是生成无图的,我们直接不用保存到联系表了
                return;
            }else if(materials.size()<3){//自动生成的是单图,保存到文章表中,以及关联表
                materials = materials.stream().limit(1).collect(Collectors.toList());
                String imagesurl = StringUtils.join(materials.toArray(), ",");
                wmNews.setImages(imagesurl);
                updateById(wmNews);
            }else {
                materials = materials.stream().limit(3).collect(Collectors.toList());//多图
                String imagesurl = StringUtils.join(materials.toArray(), ",");
                wmNews.setImages(imagesurl);
                updateById(wmNews);
            }
        }
        //不是自动,就直接将封面的图片传进来,然后去重和第5部的一样,抽取出一个方法;
        saveRelativeInfo(dto.getImages(),wmNews, (short) 1);
    }

    /**
     * 处理传递过来的图片进行去重和保存到关联表
     */
    private void saveRelativeInfo(List<String> materials, WmNews wmNews,short type){
        if (materials.size()>0&&null!=materials){
            List<String> distincturl = materials.stream().distinct().collect(Collectors.toList());//去重
            String imagestr = StringUtils.join(distincturl.toArray(), ",");
            List<WmMaterial> wmMaterials = wmMaterialMapper.selectList(Wrappers.<WmMaterial>lambdaQuery().in(WmMaterial::getUrl, imagestr));
            List<Integer> urlids = wmMaterials.stream().map(wmMaterial -> wmMaterial.getId()).collect(Collectors.toList());
            if (distincturl.size()!=urlids.size()){
                throw new CustomException(AppHttpCodeEnum.MATERIAL_REFERENCE_FAIL);//素材有的被删除了,抛出异常,不能继续执行
            }
            wmNewsMaterialMapper.saveRelations(urlids,wmNews.getId(),type);
        }
}
    @Autowired
private WmMaterialMapper wmMaterialMapper;
    /**
     * 5.保存内容中的图片到关联表中
     * @param materials
     * @param wmNews
     */
    private void saveContentImg(List<String> materials, WmNews wmNews) {
        saveRelativeInfo(materials,wmNews, (short) 0);
       /* if (materials.size()>0&&null!=materials){
            List<String> distincturl = materials.stream().distinct().collect(Collectors.toList());//去重
            String imagestr = StringUtils.join(distincturl.toArray(), ",");
            List<WmMaterial> wmMaterials = wmMaterialMapper.selectList(Wrappers.<WmMaterial>lambdaQuery().in(WmMaterial::getUrl, imagestr));
            List<Integer> urlids = wmMaterials.stream().map(wmMaterial -> wmMaterial.getId()).collect(Collectors.toList());
            if (distincturl.size()!=urlids.size()){
                throw new CustomException(AppHttpCodeEnum.MATERIAL_REFERENCE_FAIL);//素材有的被删除了,抛出异常,不能继续执行
            }
            wmNewsMaterialMapper.saveRelations(urlids,wmNews.getId(), (short) 0);
        }*/
    }

    /**
     * 4.处理文章内容中的图片,后续保存内容中的图片,以及保存封面中的图片会使用
     * @param content
     * @return
     */
    private List<String> ectractUrlInfo(String content) {
       List<String> urls=new ArrayList<>();
       //将String类型的内容转换成List<Map>类型的
        List<Map> maps = JSON.parseArray(content, Map.class);
        for (Map map : maps) {
            if ("image".equals(map.get("type"))){
                urls.add(map.get("value").toString());
            }
        }
        return urls;
    }

    @Autowired
private WmNewsMaterialMapper wmNewsMaterialMapper;
    /**
     * 2.保存或者修改文章到数据库
     * @param dto
     * @return
     */
    private WmNews saveorupdateNews(WmNewsDto dto) {
        WmNews wmNews = new WmNews();
        BeanUtils.copyProperties(dto,wmNews);//拷贝属性
        //处理type
        if (null!=dto.getType()&&dto.getType()==WemediaConstants.WM_NEWS_TYPE_AUTO){
            wmNews.setType(null);//如果是自动的话,拷贝过后还是-1,不能插入到数据库中,所以先给他设置一个空值
        }
         wmNews.setCreatedTime(new Date());
        wmNews.setSubmitedTime(new Date());
        wmNews.setEnable((short) 1);
        wmNews.setUserId(WmThreadLocalUtil.getUser().getId());//封装完成后开始进行保存或者修改操作
        if (null==dto.getId()){//为空直接保存
            save(wmNews);
        }else {
            updateById(wmNews);
            //删除关联表中的这个newId的数据
            wmNewsMaterialMapper.delete(Wrappers.<WmNewsMaterial>lambdaQuery().eq(WmNewsMaterial::getNewsId,dto.getId()));
        }
        return wmNews;
    }

    /**
     * 查看文章详情
     * @param id
     * @return
     */
    @Override
    public ResponseResult watch(Integer id) {
        WmNews wmNews = getById(id);
        return ResponseResult.okResult(wmNews);
    }

    /**
     * 删除文章
     * @param id
     * @return
     */
    @Override
    public ResponseResult deleteNew(Integer id) {
        if (null==id){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        WmNews wmNews = getById(id);
        if (null==wmNews){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        if (wmNews.getStatus()==WmNews.Status.PUBLISHED.getCode()){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        removeById(id);
        wmNewsMaterialMapper.delete(Wrappers.<WmNewsMaterial>lambdaQuery().eq(WmNewsMaterial::getNewsId,id));
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }
    @Autowired
    private WmNewsMapper wmNewsMapper;
    @Autowired
    private KafkaTemplate<String,String> kafkaTemplate;


    /**
     * 文章的上架或者下架
     * @param wmNewsDto
     * @return
     */
    @Override
    public ResponseResult DownorUp(WmNewsDto wmNewsDto) {
        /*Integer id = wmNewsDto.getId();
        if (null==id){
return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR);
        }
        WmNews wmNews = this.getOne(Wrappers.<WmNews>lambdaQuery().eq(WmNews::getId, id));
        if (null==wmNews){
            return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR);
        }
        Short status = wmNews.getStatus();
        if (status!=WmNews.Status.PUBLISHED.getCode()){
            return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR);
        }
        wmNews.setEnable(wmNewsDto.getEnable());
        this.updateById(wmNews);
        if (null!=wmNews.getArticleId()){
            HashMap<String, Object> map = new HashMap<>();
            map.put("articleId",wmNews.getArticleId());
            map.put("enable",wmNews.getEnable());
            kafkaTemplate.send("update",JSON.toJSONString(map));
        }else{
        return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR);}
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
        */
        //1.校验参数
         if (null==wmNewsDto.getId()){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID,"文章id不可缺少");
         }
        Integer id = wmNewsDto.getId();
        WmNews wmNews = wmNewsMapper.selectById(id);
        if (null==wmNews){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST,"文章不存在");
        }
        if (wmNews.getStatus()!=WmNews.Status.PUBLISHED.getCode()){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID,"当前文章不是发布状态,不能上下架");
        }
        wmNews.setEnable(wmNewsDto.getEnable());
        wmNewsMapper.updateById(wmNews);
        if (null!=wmNews.getArticleId()){
            HashMap<String, Object> map = new HashMap<>();
            map.put("articleid",wmNews.getArticleId());
            map.put("enable",wmNews.getEnable());
            kafkaTemplate.send("update",JSON.toJSONString(map));
        }else {
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST,"ArticleId不存在");
        }
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }
}
